home *** CD-ROM | disk | FTP | other *** search
Text File | 1991-05-01 | 18.5 KB | 783 lines | [TEXT/MPS ] |
- /*
- • List units defining any constants, types or classes that are required for your implementation
- section (e.g. Packages or Errors)
- • Also list units defining the classes that you declared EXTERNAL in the interface section
- or wish to use in the implementation section.
- • Also list the units required by the interfaces of the above units.
- */
-
- #include "UMenuView.h"
-
- #ifndef __UGEOMETRY__
- #include <UGeometry.h>
- #endif
-
- #ifndef __ULIST__
- #include <UList.h>
- #endif
-
- #ifndef __UEVENT__
- #include <UEvent.h>
- #endif
-
- #ifndef __UCOMMAND__
- #include <UCommand.h>
- #endif
-
- #ifndef __EDITIONS__
- #include <Editions.h>
- #endif
-
- #ifndef __DIALOGS__
- #include <Dialogs.h>
- #endif
-
- #ifndef __UAPPLICATION__
- #include <UApplication.h>
- #endif
-
- #ifndef __UDOCUMENT__
- #include <UDocument.h>
- #endif
-
- #ifndef __UFAILURE__
- #include <UFailure.h>
- #endif
-
- #ifndef __UMACAPPUTILITIES__
- #include <UMacAppUtilities.h>
- #endif
-
- #ifndef __UPATCH__
- #include <UPatch.h>
- #endif
-
- #ifndef __UMACAPPGLOBALS__
- #include <UMacAppGlobals.h>
- #endif
-
- #ifndef __UMENUMGR__
- #include <UMenuMgr.h>
- #endif
-
- #ifndef __UMEMORY__
- #include <UMemory.h>
- #endif
-
- #ifndef __ERRORS__
- #include <Errors.h>
- #endif
-
- #ifndef __TOOLUTILS__
- #include <ToolUtils.h>
- #endif
-
- #if qDebugMsg
- #ifndef __STDIO__
- #include <StdIO.h>
- #endif
- #endif
-
- //--------------------------------------------------------------------------------------------------
- Boolean gTrackingInMenu = FALSE;
-
- //--------------------------------------------------------------------------------------------------
- struct MenuRec
- {
- short mID;
- TMenuView* mObject;
- };
-
-
- typedef MenuRec MenuArray[4000];
- typedef MenuRec* MenuArrayPtr;
- typedef MenuRec** MenuArrayHandle;
-
- //--------------------------------------------------------------------------------------------------
- CGrafPort pMenuCPort; /* Color port for compatibility.
- Private grafPort used to focus the menu w/o
- messing up the Window Manager port. */
- MenuArrayHandle pMenuArray; // Used to map a MenuHandle to the TMenuView
- short pNumMenus;
- Handle pCustDefproc; // Replaces the menu's menuProc field
-
- //--------------------------------------------------------------------------------------------------
- // Returns the TickCount some time in the future.
-
- pascal long Future(long delta)
-
- {
- return TickCount() + delta;
- }
-
- //--------------------------------------------------------------------------------------------------
-
- #pragma segment MAMenuRes
-
- pascal void WaitTickChange(void)
-
- {
- long now = TickCount();
- while (TickCount() != now)
- ;
- }
-
- //--------------------------------------------------------------------------------------------------
-
- #pragma segment MAMenuRes
-
- pascal TMenuView* FindTMenuView(MenuHandle theMenu)
-
- {
- MenuArrayPtr p = *pMenuArray;
- short id = (*theMenu)->menuID;
-
- for (short i = 0; i < pNumMenus; ++i)
- if (p[i].mID == id)
- return p[i].mObject;
- return NULL;
- }
-
- //--------------------------------------------------------------------------------------------------
- // Called by the MDEF resource.
- /*$Push*/
- #if qTrace
- #pragma $D+
- #endif
-
- #pragma segment MAMenuRes
-
- pascal void MenuDefproc(short message,
- MenuHandle theMenu,
- Rect& menuRect,
- Point hitPt,
- short& whichItem)
-
- {
- long OldA5 = SetCurrentA5(); // ***** Called from trap patches *****
- TMenuView * menuObj = FindTMenuView(theMenu);
- #if qDebug
- if (menuObj == NULL)
- ProgramBreak("MenuDefproc called with no TMenuView object");
- #endif
-
- // Dispatch to the TMenuView object
- menuObj->HandleDefproc(message, theMenu, menuRect, hitPt, whichItem);
- SetA5(OldA5);
- }
- //$Pop
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAMenuInit
-
- typedef struct JMP
- {
- short opcode;
- Ptr address;
- } *JmpPtr, ** JmpHandle;
-
- pascal void InitUMenuView(void)
-
- {
- JmpHandle h;
-
- if (qNeedsColorQD || gConfiguration.hasColorQD)
- OpenCPort(&pMenuCPort);
- else
- OpenPort((GrafPtr) & pMenuCPort);
- pNumMenus = 0;
- pMenuArray = (MenuArrayHandle)NewPermHandle(0);
-
- h = (JmpHandle)NewHandle(6);
- FailNIL(h);
- (*h)->opcode = 0x4EF9;
- (*h)->address = (Ptr) & MenuDefproc;
- pCustDefproc = (Handle)h;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAMenuInit
- pascal void TMenuView::Initialize(void) // override
- {
- inherited::Initialize();
-
- fBorder = gZeroRect;
- fFlashInterval = -1;
- fHighlighted = FALSE;
- fMenuHandle = NULL;
- fNextFlash = 0;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAMenuInit
-
- pascal void TMenuView::IMenuView(short rsrcID,
- short menuWidth,
- short menuHeight)
-
- {
- MenuHandle m;
- Rect r;
- short item;
- VPoint vp(menuHeight, menuWidth);
-
- // Initialize fields
- this->IView(NULL, NULL, gZeroVPt, vp, sizeVariable, sizeVariable);
- fNextHandler = gApplication; // so postcommand flows to the app
-
- /*fFlashInterval = - 1;
- fNextFlash = 0;*/
-
- if (rsrcID == 0)
- fMenuHandle = NULL;
- else
- {
- // Read in menu and set its defproc
- m = MAGetMenu(rsrcID);
-
- if (m == NULL)
- {
- #if qDebugMsg
- fprintf(stderr, "rsrcID = %4s", (char *) &rsrcID);
- ProgramBreak("No such MENU!");
- #endif
-
- this->Free();
- Failure(resNotFound, 0);
- }
-
- ++pNumMenus;
- SetHandleSize((Handle)pMenuArray, sizeof(MenuRec) * pNumMenus);
- (*pMenuArray)[pNumMenus-1].mID = (*m)->menuID;
- (*pMenuArray)[pNumMenus-1].mObject = this;
-
- (*m)->menuProc = pCustDefproc;
- fMenuHandle = m;
-
- r = gZeroRect;
- item = 0;
- MenuDefproc(mSizeMsg, m, r, gZeroPt, item);// recompute the menu size
- }
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAMenuNever
-
- pascal short TMenuView::FindItem(Point)
-
- {
- //SubClassResponsibility();
- return 0;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAMenuRes
-
- pascal void TMenuView::PostCommand(TCommand* command)// override
- // ensure that trackers get tracked immediately
-
- {
- if (command && command->IsMemberClass(GetClassIDFromName("TTracker")))
- {
- ++(gApplication->fEventLevel);
- command->Process(); //!!! this->PerformCommand((TTracker*) command);
- --(gApplication->fEventLevel);
- }
- else
- inherited::PostCommand(command);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAMenuRes
-
- pascal void TMenuView::HandleDefproc(short message,
- MenuHandle theMenu,
- Rect& menuRect,
- Point hitPt,
- short& whichItem)
-
- {
- GrafPtr savePort;
- Rect r;
- VRect VMenuRect;
- VPoint VHitPt;
-
- // Save the wmgr port && set our private port
- GetPort(savePort);
-
- SetPort((GrafPtr) & pMenuCPort);
- // Match the location and size that the menu mgr gives us
- MovePortTo(menuRect.left, menuRect.top);
- PortSize(menuRect.Length(hSel), menuRect.Length(vSel));
- fLocation.h = menuRect.left;
- fLocation.v = menuRect.top;
-
- this->UpdateCoordinates();
- if (this->Focus())
- {
- GlobalToLocal(hitPt);
- GlobalToLocal(menuRect[topLeft]);
- GlobalToLocal(menuRect[botRight]);
-
- this->SetEnable((((*fMenuHandle)->enableFlags) & 1) != 0);
- switch (message)
- {
- case mDrawMsg:
- #if qDebugMsg
- if (gIntenseDebugging)
- fprintf(stderr, "mDrawMsg");
- #endif
-
- this->HandleDrawMessage(message, theMenu, menuRect, hitPt, whichItem);
- break;
-
- case mChooseMsg:
- #if qDebugMsg
- if (gIntenseDebugging)
- fprintf(stderr, "mChooseMsg");
- #endif
-
- this->HandleChooseMessage(message, theMenu, menuRect, hitPt, whichItem);
- break;
-
- case mSizeMsg:
- #if qDebugMsg
- if (gIntenseDebugging)
- fprintf(stderr, "mSizeMsg");
- #endif
-
- this->HandleSizeMessage(message, theMenu, menuRect, hitPt, whichItem);
- break;
-
- case mPopUpMsg:
- #if qDebugMsg
- if (gIntenseDebugging)
- fprintf(stderr, "mPopUpMsg");
- #endif
-
- this->HandlePopUpMessage(message, theMenu, menuRect, hitPt, whichItem);
- break;
-
- #if qDebugMsg
- default:
- if (gIntenseDebugging)
- fprintf(stderr, "otherwise message");
- break;
- #endif
-
- }
-
- LocalToGlobal(menuRect[topLeft]);
- LocalToGlobal(menuRect[botRight]);
-
- this->InvalidateFocus();
- }
-
- SetPort(savePort);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAMenuRes
-
- pascal void TMenuView::HandleChooseMessage(short,
- MenuHandle,
- Rect& ,
- Point hitPt,
- short& whichItem)
-
- {
- short newItem = kNoMenuItem;
- Boolean saveTrackingInMenu = gTrackingInMenu;
-
- // so that trackers get a chance to know that they're tracking in menus
- gTrackingInMenu = TRUE;
-
- if (this->IsEnabled()) // menu enabled
- {
- Rect hitRect(0, 0, 0, 0);
-
- // see if point is within hit area
- this->GetQDExtent(hitRect);
- hitRect[topLeft] += fBorder[topLeft];
- hitRect[botRight] += fBorder[botRight];
-
- if (hitRect.Contains(hitPt)) // in menu (not border)
- {
- TToolboxEvent * event = NULL;
- EventRecord anEventRecord;
-
- // NOTE: Either your subclass of TTearOffMenu should override DoMouseCommand or one of
- // TTearOffMenu's view's subview's should override DoMouseCommand so that it
- // creates and posts a TTracker. TTearOffMenu's override of PostCommand will
- // ensure that the tracker is tracked immediately. The tracker, having been
- // posted and tracked, will then get executed next time PerformCommand is
- // called. So, when we're done with HandleMouseDown below, we simply tell the
- // menu manager that no menu item was selected, ie newItem == kNoMenuItem.
-
- this->CreateMouseDownEventInfo(hitPt, anEventRecord, event);
- if (!HandleMouseDown(hitPt, event, gStdHysteresis))
- {
- // NOTE: for backwards compatibility with MacApp 2.0 - override your TMenuView subclass'
- // HandleMouseDown method to return FALSE, and all should work as before
-
- newItem = this->FindItem(hitPt);
- this->UpdateHighlight(whichItem, newItem);// Update highlighting
- }
- }
- }
- else
- this->UpdateHighlight(whichItem, newItem); // Update highlighting
-
- gTrackingInMenu = saveTrackingInMenu;
-
- // Tell MenuManager about new item
- whichItem = newItem;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAMenuRes
-
- pascal void TMenuView::HandleDrawMessage(short,
- MenuHandle,
- Rect& ,
- Point,
- short&)
-
- {
- this->DrawContents();
- fHighlighted = false;
- if (!IsEnabled())
- {
- Rect extent(0, 0, 0, 0);
- PenPat(qd.gray);
- PenMode(notSrcBic);
- this->GetQDExtent(extent);
- PaintRect(extent);
- }
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAMenuRes
-
- pascal void TMenuView::HandleSizeMessage(short,
- MenuHandle,
- Rect& ,
- Point,
- short&)
-
- {
- VPoint vp(0, 0);
-
- this->ComputeSize(vp);
- (*fMenuHandle)->menuWidth = (short)vp.h;
- (*fMenuHandle)->menuHeight = (short)vp.v;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAMenuRes
-
- pascal void TMenuView::HandlePopUpMessage(short,
- MenuHandle,
- Rect& menuRect,
- Point hitPt,
- short&)
-
- {
- VPoint vp(0, 0);
-
- // SubPt(origin, hitPt);
-
- menuRect.top = hitPt.h;
- menuRect.left = hitPt.v;
- this->ComputeSize(vp);
- menuRect.bottom = (short)(menuRect.top + vp.v);
- menuRect.right = (short)(menuRect.left + vp.h);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAMenuRes
-
- pascal void TMenuView::Highlight(short,
- Boolean)
-
- {
- this->SubClassResponsibility();
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAFields
-
- pascal void TMenuView::Fields(TObject* obj) // override
-
- {
- obj->DoToField("fFlashInterval", (Ptr) & fFlashInterval, bLongInt);
- obj->DoToField("fNextFlash", (Ptr) & fNextFlash, bLongInt);
- obj->DoToField("fHighlighted", (Ptr) & fHighlighted, bBoolean);
- obj->DoToField("fMenuHandle", (Ptr) & fMenuHandle, bHandle);
- obj->DoToField("fBorder", (Ptr) & fBorder, bRect);
-
- inherited::Fields(obj);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAMenuRes
- pascal Boolean TMenuView::IsItemEnabled(short item)
-
- {
- return (*fMenuHandle)->enableFlags & item;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAMenuRes
-
- pascal void TMenuView::GetMenuViewColors(short theMenu,
- short theItem,
- MenuColors& theMenuColors)
-
- {
- typedef char TypeOfMenuInfo;
- enum
- {
- aMenuItem = 0
- };
-
-
- enum
- {
- aMenuTitle = 1
- };
-
-
- enum
- {
- aMenuBar = 2
- };
-
-
- enum
- {
- noType = 3
- };
-
-
- MCEntryPtr aMCEntryPtr;
- TypeOfMenuInfo typeOfRequest;
- TypeOfMenuInfo typeOfEntryFound;
- short theEntryMenu = theMenu;
- short theEntryItem = theItem;
-
- if (qNeedsColorQD || gConfiguration.hasColorQD)
- {
- if (theItem != 0)
- typeOfRequest = aMenuItem;
- else if (theMenu != 0)
- typeOfRequest = aMenuTitle;
- else
- typeOfRequest = aMenuBar;
-
- aMCEntryPtr = GetMCEntry(theEntryMenu, theEntryItem);
- if (aMCEntryPtr == NULL) // not found, try as title
- {
- theEntryItem = 0;
- aMCEntryPtr = GetMCEntry(theEntryMenu, theEntryItem);
- if (aMCEntryPtr == NULL) // not found, try as menubar
- {
- theEntryMenu = 0;
- aMCEntryPtr = GetMCEntry(theEntryMenu, theEntryItem);
- }
- }
-
- if (aMCEntryPtr == NULL)
- typeOfEntryFound = noType;
- else
- {
- if (theEntryItem != 0)
- typeOfEntryFound = aMenuItem;
- else if (theEntryMenu != 0)
- typeOfEntryFound = aMenuTitle;
- else
- typeOfEntryFound = aMenuBar;
- }
-
- switch (typeOfEntryFound)
- {
- case aMenuItem:
- theMenuColors.itemColor = (*aMCEntryPtr).mctRGB1;
- theMenuColors.backgroundColor = (*aMCEntryPtr).mctRGB4;
- theMenuColors.markColor = (*aMCEntryPtr).mctRGB1;
- theMenuColors.commandColor = (*aMCEntryPtr).mctRGB1;
- break;
-
- case aMenuTitle:
- switch (typeOfRequest)
- {
- case aMenuItem:
- {
- theMenuColors.itemColor = (*aMCEntryPtr).mctRGB3;
- theMenuColors.backgroundColor = (*aMCEntryPtr).mctRGB4;
- theMenuColors.markColor = (*aMCEntryPtr).mctRGB3;
- theMenuColors.commandColor = (*aMCEntryPtr).mctRGB3;
- break;
- }
- case aMenuTitle:
- {
- theMenuColors.itemColor = (*aMCEntryPtr).mctRGB1;
- theMenuColors.backgroundColor = (*aMCEntryPtr).mctRGB2;
- theMenuColors.markColor = (*aMCEntryPtr).mctRGB1;
- theMenuColors.commandColor = (*aMCEntryPtr).mctRGB1;
- break;
- }
- }
- break;
-
- case aMenuBar:
- switch (typeOfRequest)
- {
- case aMenuItem:
- theMenuColors.itemColor = (*aMCEntryPtr).mctRGB3;
- theMenuColors.backgroundColor = (*aMCEntryPtr).mctRGB2;
- theMenuColors.markColor = (*aMCEntryPtr).mctRGB3;
- theMenuColors.commandColor = (*aMCEntryPtr).mctRGB3;
- break;
-
- case aMenuTitle:
- theMenuColors.itemColor = (*aMCEntryPtr).mctRGB1;
- theMenuColors.backgroundColor = (*aMCEntryPtr).mctRGB4;
- theMenuColors.markColor = (*aMCEntryPtr).mctRGB1;
- theMenuColors.commandColor = (*aMCEntryPtr).mctRGB1;
- break;
-
- case aMenuBar:
- theMenuColors.itemColor = (*aMCEntryPtr).mctRGB1;
- theMenuColors.backgroundColor = (*aMCEntryPtr).mctRGB4;
- theMenuColors.markColor = (*aMCEntryPtr).mctRGB1;
- theMenuColors.commandColor = (*aMCEntryPtr).mctRGB1;
- break;
- }
- break;
-
- case noType:
- theMenuColors.itemColor = gRGBBlack;
- theMenuColors.backgroundColor = gRGBWhite;
- theMenuColors.markColor = gRGBBlack;
- theMenuColors.commandColor = gRGBBlack;
- break;
- }
- }
- else
- {
- theMenuColors.itemColor = gRGBBlack;
- theMenuColors.backgroundColor = gRGBWhite;
- theMenuColors.markColor = gRGBBlack;
- theMenuColors.commandColor = gRGBBlack;
- }
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAMenuRes
-
- pascal void TMenuView::UpdateHighlight(short oldItem,
- short newItem)
-
- {
- // Update highlighting
- if (newItem == oldItem)
- {
- if (fFlashInterval >= 0)
- if (TickCount() > fNextFlash)
- {
- fHighlighted =!fHighlighted;
- this->Highlight(oldItem, fHighlighted);
- fNextFlash = Future(fFlashInterval);
- }
- }
- else
- {
- if (fHighlighted)
- if (oldItem != kNoMenuItem)
- this->Highlight(oldItem, false);
-
- fHighlighted = (newItem != kNoMenuItem);
- if (fHighlighted)
- this->Highlight(newItem, TRUE);
-
- if (fFlashInterval >= 0)
- fNextFlash = Future(fFlashInterval);
- }
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAMenuRes
-
- pascal Boolean TMenuView::Focus(void) // override
-
- {
- Rect r;
- VPoint vorigin;
- MenuColors theMenuColors;
-
- if (inherited::Focus())
- {
- /* Try to make the best match for the menu colors without requiring programmer intervention.
- by setting the color environment to be for items. */
-
- this->GetMenuViewColors((*fMenuHandle)->menuID, 1, theMenuColors);
- SetIfColor(theMenuColors.itemColor);
- SetIfBkColor(theMenuColors.backgroundColor);
- return TRUE;
- }
- else
- return FALSE;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAMenuRes
-
- pascal void TMenuView::CreateMouseDownEventInfo(Point hitPt,
- EventRecord& anEventRecord,
- TToolboxEvent* event)
-
- {
- // !!! it would be nice to ask the application for these values from the last EventInfo
- anEventRecord.what = mouseDown;
- anEventRecord.message = 0;
- anEventRecord.when = TickCount();
- anEventRecord.where = hitPt;
- anEventRecord.modifiers = 0;
-
- event->fEventRecord = anEventRecord;
- event->fBtnState = Button();
- event->fCmdKey = IsCommandKeyDown();
- event->fShiftKey = FALSE;
- event->fAlphaLock = FALSE;
- event->fOptionKey = IsOptionKeyDown();
- event->fControlKey = FALSE;
- event->fAutoKey = FALSE;
- event->fCharacter = (char)0;
- event->fKeyCode = 0;
- event->fClickCount = gApplication->fClickCount;
- event->fAffectsMenus = FALSE;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAMenuRes
-
- pascal Boolean TMenuView::FocusOnSuperView(void)// override
-
- {
- SetPort((GrafPtr) & pMenuCPort);
- ClipRect(qd.thePort->portRect);
- return TRUE;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAMenuRes
-
- pascal GrafPtr TMenuView::GetGrafPort(void) // override
-
- {
- return (GrafPtr) & pMenuCPort;
- }
-
-
-